package cn.bugstack.mybatis.scripting.defaults;

import cn.bugstack.mybatis.executor.parameter.ParameterHandler;
import cn.bugstack.mybatis.mapping.BoundSql;
import cn.bugstack.mybatis.mapping.MappedStatement;
import cn.bugstack.mybatis.mapping.ParameterMapping;
import cn.bugstack.mybatis.reflection.MetaClass;
import cn.bugstack.mybatis.reflection.MetaObject;
import cn.bugstack.mybatis.session.Configuration;
import cn.bugstack.mybatis.type.JdbcType;
import cn.bugstack.mybatis.type.TypeHandler;
import cn.bugstack.mybatis.type.TypeHandlerRegistry;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * @author wcc
 * @description 默认参数处理器
 * @create
 */

public class DefaultParameterHandler implements ParameterHandler {
    private Logger logger = LoggerFactory.getLogger(DefaultParameterHandler.class);
    private final TypeHandlerRegistry typeHandlerRegistry;
    private final MappedStatement mappedStatement;
    private final Object parameterObject;
    private Configuration configuration;
    private BoundSql boundSql;
    public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql){
        this.mappedStatement = mappedStatement;
        this.boundSql = boundSql;
        this.parameterObject = parameterObject;
        this.configuration = mappedStatement.getConfiguration();
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    }
    @Override
    public Object getParameterObject() {
        return parameterObject;
    }

    //通过反射新建参数 并传递给statement
    @Override
    public void setParameters(PreparedStatement ps) throws SQLException {
        //获取这条sql参数列表映射表 其实是#{}里的参数
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if (null != parameterMappings){
            for (int i = 0; i < parameterMappings.size(); i++){
                ParameterMapping parameterMapping = parameterMappings.get(i);
                String propertyName = parameterMapping.getProperty();
                Object value;
                //查看这条sql对应的接口方法获取的参数是否有对应的TypeHandler 如果是基础类会有 如果是User这种类没有
                if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())){
                    value = parameterObject;
                }else {
                    //这种情况说明参数（#{}里的）是接口方法参数的属性 通过以下方式获取值
                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
                    value = metaObject.getValue(propertyName);
                }
                JdbcType jdbcType = parameterMapping.getJdbcType();

                //设置参数
                logger.info("根据每个ParameterMapping中的TypeHandler设置对应的参数信息 value：{}", JSON.toJSONString(value));
                TypeHandler typeHandler = parameterMapping.getTypeHandler();
                typeHandler.setParameter(ps,i + 1, value, jdbcType);
            }

        }
    }
}
